

function isFunction(a){
  return typeof a === 'function'
}
function isArray(a){
  return Object.prototype.toString.call(a) == '[object Array]'
}
function isObject(a){
  return Object.prototype.toString.call(a) === '[object Object]'
}
function isString(a){
  return Object.prototype.toString.call(a) ==='[object String]'
}
function isNumber(a){
  return Object.prototype.toString.call(a) ==='[object Number]'
}
function isBoolean(a){
  return Object.prototype.toString.call(a) ==='[object Boolean]'
}

function toArray(a){
  return [].slice.call(a)
}
// 本文件中的函数全 curring

function partial(fn,args){
  return function(){
    var narg = [].slice.call(arguments)
    return fn.apply(null,args.concat(narg))
  }
}
function curryN(n,fn){
  return function(){
    var narg = [].slice.call(arguments)
    if(n > narg.length){
      return curryN(n-narg.length,partial(fn,narg))
    }else{
      return fn.apply(null,narg)
    }
  }
}

function curry(fn){
  return curryN(fn.length,fn)
}

var overi  = curry(function overi_(key,fn,obj){
  if(isArray(key)){
    var keys = key
    if(keys.length == 0){
      return obj
    }else if(keys.length == 1){
      return overi(keys[0],fn,obj)
    }else{
      var h = keys[0]
      var tail = keys.slice(1)
      return overi(h
        ,alway(overi(tail,fn, obj[h]==null?{}:obj[h]))
        ,obj)
    }
  }else if(isString(key)){
    return _fn(fn)
  }else{
    throw "key 只支持数组和字符串"
  }

  function _fn(fn){
    var r = {}
    if(key in obj){
      void null
    }else{
      r[key] = fn()
    }
    for(var okey in obj){
      if(obj.hasOwnProperty(okey)){
        if(okey == key){
          r[okey] = fn(obj[okey])
        }else{
          r[okey] = obj[okey]
        }
      }else{
        void null
      }
    }
    return r
  }
})
function alway(a){
  return function(){
    return a
  }
}
var over = curry(function over_(key,val,obj){
  return overi(key,alway(val),obj)
})

function pipe(){
  var fns = [].slice.call(arguments)
  function _fn(fns){
    return function(){
      var arg = [].slice.call(arguments)
      var result = fns[0].apply(null,arg)
      for(var i=1;i<fns.length;i++){
        result = fns[i].apply(null,[result])
      }
      return result
    }
  }
  return _fn(fns)
}
function pip(arg){
  return pipe.apply(null,[].slice.call(arguments).slice(1))(arg)
}
var map = curry(function map_(fn,xs){
  var r = []
  for(var i=0;i<xs.length;i++){
    r.push(fn(xs[i]))
  }
  return r
})
var Nothing = {'@placeholder@':'Nothing'}
var find = curry(function find_(fn,xs){
  for(var i=0;i<xs.length;i++){
    if(fn(xs[i])){
      return xs[i]
    }else{
      void Nothing
    }
  }
  return Nothing
})

function isEmpty(x){
  return x==null||x == ''
}

var all = curry(function all_(fn,xs){
  for(var i=0;i<xs.length;i++){
    if(fn(xs[i]) == false) return false
    else void null
  }
  return true
})
var any = curry(function any_(fn,xs){
  for(var i=0;i<xs.length;i++){
    if(fn(xs[i]) == true) return true
    else void null
  }
  return false
})
function id(a){return a}
function not(a) {return !a}
module.exports ={
  Nothing:Nothing,
  find:find,
  pip:pip,
  pipe:pipe,
  over:over,
  overi:overi,
  curry:curry,
  curryN:curryN,
  isEmpty:isEmpty,
  map:map,
  any:any,
  all:all,
  id:id,
  not:not
}